package com.budwk.app.sqfwDoc.codeGeneratorV2.generate;

import cn.hutool.core.date.DateUtil;
import com.budwk.app.sqfwDoc.codeGenerator.cusType.SqfwImage;
import com.budwk.app.sqfwDoc.codeGenerator.pdfGenerate.AbstractCustomerPdfCreateField;
import com.budwk.app.sqfwDoc.codeGeneratorV2.fileParam.BusinessParam;
import com.budwk.app.sqfwDoc.codeGeneratorV2.fileParam.CommonParam;
import com.budwk.app.sqfwDoc.codeGeneratorV2.fileParam.PdfGenerateParam;
import com.budwk.app.util.poiUtils.CommonFormOfficeUtils;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.policy.RenderPolicy;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.budwk.app.util.poiUtils.CommonFormOfficeUtils.*;

/**
 * @author ZY.Wang
 * @since 2024/1/23
 */
@Slf4j
public abstract class BasePdfGenerator {

    private String fileIdentity;

    //  时间格式map，key为字段的名称，value为时间格式
    private final Map<String, String> dateFormatMap = Maps.newHashMap();

    protected void initDateFormatMap() {
        this.dateFormatMap.put("fillDateStr", "yyyy-MM-dd");
    }

    /**
     * 创建pdf
     *
     * @param pdfGenerateParam pdf创建所需要提供的参数
     * @return pdf创建结果
     */
    public ResultOfPdfGenerator createPdf(PdfGenerateParam pdfGenerateParam) {

        ResultOfPdfGenerator result = new ResultOfPdfGenerator();

        // 初始化时间格式
        initDateFormatMap();

        // 检查pdf是否满足生成条件
        boolean createFileFlag = pdfCreateConditionCheck(pdfGenerateParam);
        if (!createFileFlag) {
            return null;
        }

        // 填充基础信息
        Map<String, Object> paramMap = Maps.newHashMap();
        popularBasePdfParam(paramMap, pdfGenerateParam);

        // 利用反射填充其他字段信息
        popularAbstractCustomerParam(paramMap, pdfGenerateParam.getAbstractCustomerPdfCreateField());

        // 用户自定义填充字段
        customerPopularPdfParam(paramMap, pdfGenerateParam);

        // 获取模板名称
        String templateName = getTemplatePath(pdfGenerateParam);

        // 用户自定义创建页脚
        Map<String, Object> footerMap = createFooterMap(pdfGenerateParam);

        // 用户自定义渲染插件
        Map<String, RenderPolicy> policyMap = createCustomerRenderPolicy(paramMap, pdfGenerateParam);

        XWPFTemplate template = generateWordDocument(paramMap, footerMap, policyMap, templateName);

        // 生成之后可以在generator层自定义操作
        createXWPDFTemplateAfter(template, pdfGenerateParam);

        result.setPdfXWPFTemplate(template);

        customerPopularResultBridgeMap(result,pdfGenerateParam);

        return result;
    }

    protected void customerPopularResultBridgeMap(ResultOfPdfGenerator result, PdfGenerateParam pdfGenerateParam) {

    }

    /**
     * pdf创建之后还可以做的操作，比如添加印章等
     *
     * @param template         模板文件
     * @param pdfGenerateParam 创建pdf所提供的参数
     * @return 结果
     */
    public ByteArrayOutputStream generatePDFAfter(ResultOfPdfGenerator template, PdfGenerateParam pdfGenerateParam) {
        return null;
    }

    /**
     * 填充一些基础的固定的参数
     *
     * @param paramMap         pdf参数map
     * @param pdfGenerateParam 创建pdf需要的参数
     */
    private void popularBasePdfParam(Map<String, Object> paramMap, PdfGenerateParam pdfGenerateParam) {
        CommonParam createUserParam = pdfGenerateParam.getCreateUserCommonParam();

        Class<CommonParam> commonParamClass = CommonParam.class;
        Field[] declaredFields = commonParamClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            String fieldName = declaredField.getName();
            Object fieldData = null;
            try {
                fieldData = declaredField.get(createUserParam);
                if (fieldData != null && Date.class.isAssignableFrom(declaredField.getType())) {
                    Date fieldDataOfDate = (Date) fieldData;
                    String dateStr = dateFormatHandler(fieldName, fieldDataOfDate);
                    paramMap.put(fieldName, dateStr);
                    continue;
                }

                if (fieldData != null) paramMap.put(fieldName, fieldData);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 填充创建人签名部分
        String createUserName = createUserParam.getCreateUserName();
        String createUserSigUrl = createUserParam.getCreateUserSigUrl();
        List<String> createUsernameList = Lists.newArrayList();
        List<String> createUserSigUrlList = Lists.newArrayList();

        if (StringUtils.isBlank(createUserSigUrl)) {
            createUsernameList.add(createUserName);
        } else {
            createUserSigUrlList.add(createUserSigUrl);
        }
        addWordUserSignature(paramMap, "cuNoSig", "cuSigs", "cuSig", createUsernameList, createUserSigUrlList, 1.0F);

        BusinessParam businessParam = pdfGenerateParam.getBusinessParam();
        Date fillDate = new Date();
        if (businessParam != null) {
            fillDate = businessParam.getFillDate();
        }
        if (fillDate == null) fillDate = new Date();
        paramMap.put("fillDateStr", DateUtil.format(fillDate, "yyyy-MM-dd"));
    }

    /**
     * 通过反射填充用户自定义数据
     *
     * @param paramMap                       参数map
     * @param abstractCustomerPdfCreateField 用户自定义字段
     */
    public void popularAbstractCustomerParam(Map<String, Object> paramMap, AbstractCustomerPdfCreateField abstractCustomerPdfCreateField) {

        Class<? extends AbstractCustomerPdfCreateField> fieldClass = abstractCustomerPdfCreateField.getClass();

        Field[] declaredFields = fieldClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);

            String fieldName = declaredField.getName();
            Object fieldData = null;
            try {
                fieldData = declaredField.get(abstractCustomerPdfCreateField);
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (fieldData == null && !SqfwImage.class.isAssignableFrom(declaredField.getType())) {
                paramMap.put(fieldName, "");
                continue;
            }

            // 分不同的类型进行处理，如果是字符串的话，可以直接插入数据
            if (String.class.isAssignableFrom(declaredField.getType())) {
                String fieldDataStr = (String) fieldData;
                paramMap.put(fieldName, fieldDataStr);
            }

            // 如果是时间类型，则使用默认的时间格式进行转化
            if (Date.class.isAssignableFrom(declaredField.getType())) {
                Date fileDate = (Date) fieldData;
                String dateStr = dateFormatHandler(fieldName, fileDate);
                paramMap.put(fieldName, dateStr);
            }

            // 如果是照片类型则转化为图片
            if (SqfwImage.class.isAssignableFrom(declaredField.getType())) {
                if (fieldData != null) {
                    SqfwImage imageData = (SqfwImage) fieldData;

                    List<String> pictureUrlList = imageData.getImageUrlList();
                    List<Map<String, PictureRenderData>> pictures = CommonFormOfficeUtils.addWordPicture(pictureUrlList, fieldName, 11F);
                    paramMap.put(fieldName + "s", pictures);
                } else {
                    paramMap.put(fieldName + "s", Lists.newArrayList());
                }
            }

            if (fieldData instanceof Integer || fieldData instanceof Double || fieldData instanceof Long ||
                    fieldData instanceof Boolean) {
                paramMap.put(fieldName, fieldData);
            }
        }
    }

    /**
     * 特殊时间字段格式处理器
     *
     * @param fieldName 字段名称
     * @param date      时间
     * @return 结果
     */
    private String dateFormatHandler(String fieldName, Date date) {
        String defaultDateFormat = "yyyy-MM-dd";

        String dateFormat = defaultDateFormat;
        if (dateFormatMap.containsKey(fieldName)) {
            dateFormat = dateFormatMap.get(fieldName);
        }

        try {
            return DateUtil.format(date, dateFormat);
        } catch (Exception e) {
            return DateUtil.format(date, defaultDateFormat);
        }
    }

    /**
     * 用户可以自定义文本角标
     *
     * @param pdfGenerateParam 创建pdf所提供的参数
     * @return 结果
     */
    protected Map<String, Object> createFooterMap(PdfGenerateParam pdfGenerateParam) {
        return null;
    }

    /**
     * 允许用户自定义渲染方法
     *
     * @param paramMap         参数
     * @param pdfGenerateParam 参数
     * @return 结果
     */
    protected Map<String, RenderPolicy> createCustomerRenderPolicy(Map<String, Object> paramMap, PdfGenerateParam pdfGenerateParam) {
        return null;
    }

    /**
     * 允许在生成XWPDf文件之后进行擦操作
     *
     * @param template         XWPDF文件
     * @param pdfGenerateParam 生成pdf的参数
     */
    protected void createXWPDFTemplateAfter(XWPFTemplate template, PdfGenerateParam pdfGenerateParam) {

    }

    /**
     * 根据参数判断是否能够生成文件
     *
     * @param pdfGenerateParam pdf生成参数
     * @return 结果
     */
    protected abstract boolean pdfCreateConditionCheck(PdfGenerateParam pdfGenerateParam);

    /**
     * 根据参数用户自定义填充数据
     *
     * @param paramMap         pdf参数map
     * @param pdfGenerateParam pdf创建所需参数
     */
    protected abstract void customerPopularPdfParam(Map<String, Object> paramMap, PdfGenerateParam pdfGenerateParam);

    /**
     * 获取模板路径
     *
     * @return 结果
     */
    protected abstract String getTemplatePath(PdfGenerateParam pdfGenerateParam);

    public String getFileIdentity() {
        return fileIdentity;
    }

    public void setFileIdentity(String fileIdentity) {
        this.fileIdentity = fileIdentity;
    }
}
